<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
	<title>cardinality 聚合 | ElasticSearch 7.7 权威指南中文版</title>
	<meta name="keywords" content="ElasticSearch 权威指南中文版, elasticsearch 7, es7, 实时数据分析，实时数据检索" />
    <meta name="description" content="ElasticSearch 权威指南中文版, elasticsearch 7, es7, 实时数据分析，实时数据检索" />
    <!-- Give IE8 a fighting chance -->
    <!--[if lt IE 9]>
    <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
    <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
	<link rel="stylesheet" type="text/css" href="../static/styles.css" />
	<script>
	var _link = 'search-aggregations-metrics-cardinality-aggregation.html';
    </script>
</head>
<body>
<div class="main-container">
    <section id="content">
        <div class="content-wrapper">
            <section id="guide" lang="zh_cn">
                <div class="container">
                    <div class="row">
                        <div class="col-xs-12 col-sm-8 col-md-8 guide-section">
                            <div style="color:gray; word-break: break-all; font-size:12px;">原英文版地址: <a href="https://www.elastic.co/guide/en/elasticsearch/reference/7.7/search-aggregations-metrics-cardinality-aggregation.html" rel="nofollow" target="_blank">https://www.elastic.co/guide/en/elasticsearch/reference/7.7/search-aggregations-metrics-cardinality-aggregation.html</a>, 原文档版权归 www.elastic.co 所有<br/>本地英文版地址: <a href="../en/search-aggregations-metrics-cardinality-aggregation.html" rel="nofollow" target="_blank">../en/search-aggregations-metrics-cardinality-aggregation.html</a></div>
                        <!-- start body -->
                  <div class="page_header">
<strong>重要</strong>: 此版本不会发布额外的bug修复或文档更新。最新信息请参考 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html" rel="nofollow">当前版本文档</a>。
</div>
<div id="content">
<div class="breadcrumbs">
<span class="breadcrumb-link"><a href="index.html">Elasticsearch 权威指南 [7.7]</a></span>
»
<span class="breadcrumb-link"><a href="search-aggregations.html">聚合</a></span>
»
<span class="breadcrumb-link"><a href="search-aggregations-metrics.html">度量聚合</a></span>
»
<span class="breadcrumb-node">cardinality 聚合</span>
</div>
<div class="navheader">
<span class="prev">
<a href="search-aggregations-metrics-boxplot-aggregation.html">« boxplot 聚合</a>
</span>
<span class="next">
<a href="search-aggregations-metrics-stats-aggregation.html">stats 聚合 »</a>
</span>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h2 class="title">
<a id="search-aggregations-metrics-cardinality-aggregation"></a>基数(cardinality)聚合
</h2>
</div></div></div>
<p>
计算不同值的近似计数的<code class="literal">single-value(单值)</code>度量聚合。

值可以从文档的给定的字段中提取，也可以由脚本生成。
</p>
<p>
假设你正在对商店的销售数据进行索引，并希望计算符合查询条件的已售出产品的唯一数量:
</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">POST /sales/_search?size=0
{
    "aggs" : {
        "type_count" : {
            "cardinality" : {
                "field" : "type"
            }
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/334.console"></div>
<p>请求的响应：</p>
<div class="pre_wrapper lang-console-result">
<pre class="programlisting prettyprint lang-console-result">{
    ...
    "aggregations" : {
        "type_count" : {
            "value" : 3
        }
    }
}</pre>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_precision_control"></a>精度控制
</h3>
</div></div></div>
<p>此聚合还支持 <code class="literal">precision_threshold</code> 选项：</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">POST /sales/_search?size=0
{
    "aggs" : {
        "type_count" : {
            "cardinality" : {
                "field" : "type",
                "precision_threshold": 100 <a id="CO184-1"></a><i class="conum" data-value="1"></i>
            }
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/335.console"></div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO184-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p>
<code class="literal">precision_threshold</code> 选项允许用内存换取准确性，并定义一个唯一的计数，低于该计数时，计数将接近准确值。

超过这个值，计数可能会变得有点模糊。

支持的最大值是 40000，超过该值的阈值将与阈值 40000 具有相同的效果。默认值为<code class="literal">3000</code>。
</p>
</td>
</tr>
</table>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_counts_are_approximate"></a>计数是近似值
</h3>
</div></div></div>
<p>
计算精确的计数需要将值加载到一个哈希集合中并返回其大小。

当处理高基数集合和(或)大值时，这是不可伸缩的，因为所需的内存使用量以及在节点之间传递每个分片的集合会占用太多的集群资源。
</p>
<p>
这种 <code class="literal">cardinality</code> 聚合基于 <a href="http://static.googleusercontent.com/media/research.google.com/fr//pubs/archive/40671.pdf" class="ulink" target="_top">HyperLogLog++</a> 算法，该算法基于具有一些有趣属性的值的散列进行计数：
</p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
可配置的精度，决定如何用内存交换精度，  
</li>
<li class="listitem">
在低基数集合上有极好的准确性，
</li>
<li class="listitem">
固定的内存使用量：无论是有数百个还是数十亿个唯一值，内存使用量仅取决于配置的精度。
</li>
</ul>
</div>
<p>
对于精度阈值 <code class="literal">c</code>，我们实现它时大约需要 <code class="literal">c * 8</code> 个字节。
</p>
<p>
下图显示了阈值前后误差的变化情况：
</p>
<p><span class="image"><img src="../static/images/cardinality_error.png" alt="cardinality error"></span></p>
<p>
对于所有的 3 个阈值来说，计数都精确到了配置的阈值。

虽然不能保证，但很可能是这样。

实际的准确性取决于所讨论的数据集。

总的来说，大多数数据集显示出一贯良好的准确性。

还要注意，即使阈值低至 100，即使在计算数百万个项目时，误差仍然很低(如上图所示，1-6%)。
</p>
<p>
HyperLogLog++ 算法依赖于散列值的前导零，散列在数据集中的确切分布会影响基数的准确性。
</p>
<p>
还请注意，即使阈值低至 100，误差仍然很低，即使在计算数百万个项目时。
</p>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_pre_computed_hashes"></a>预先计算的哈希值 (pre-computed hashes)
</h3>
</div></div></div>
<p>
对于具有高基数的 string 字段，将字段值的散列存储在索引中，然后对该字段运行 cardinality 聚合可能会更快。

这可以通过从客户端提供哈希值或使用<a href="https://www.elastic.co/guide/en/elasticsearch/plugins/7.7/mapper-murmur3.html" class="ulink" target="_top" rel="nofollow"><code class="literal">mapper-murmur3</code></a> 插件让 Elasticsearch 计算哈希值来实现。
</p>
<div class="note admon">
<div class="icon"></div>
<div class="admon_content">
<p>
预先计算散列通常只对非常大和(或)高基数的字段有用，因为它节省了CPU和内存。

但是，在 numeric 字段上，散列非常快，存储原始值所需的内存与存储散列所需的内存差不多。

对于低基数 string 字段也是如此，特别是考虑到这些字段已经过优化，以确保每个段的每个唯一值最多计算一次散列。
</p>
</div>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_script_4"></a>脚本(script)
</h3>
</div></div></div>
<p>
<code class="literal">cardinality</code> 度量支持脚本，但是性能会受到明显影响，因为散列需要动态计算。
</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">POST /sales/_search?size=0
{
    "aggs" : {
        "type_promoted_count" : {
            "cardinality" : {
                "script": {
                    "lang": "painless",
                    "source": "doc['type'].value + ' ' + doc['promoted'].value"
                }
            }
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/336.console"></div>
<p>
这将把参数 <code class="literal">script</code> 解释为一个 <code class="literal">inline</code>(内联) 脚本，使用<code class="literal">painless</code>(无痛) 脚本语言，没有脚本参数。

要使用一个已存储的脚本，请使用以下语法：
</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">POST /sales/_search?size=0
{
    "aggs" : {
        "type_promoted_count" : {
            "cardinality" : {
                "script" : {
                    "id": "my_script",
                    "params": {
                        "type_field": "type",
                        "promoted_field": "promoted"
                    }
                }
            }
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/337.console"></div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_missing_value_3"></a>缺失的值
</h3>
</div></div></div>
<p>
参数 <code class="literal">missing</code> 定义应该如何处理有缺失值的文档。 默认情况下，它们会被忽略，但也可以将它们视为有一个(默认)值。
</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">POST /sales/_search?size=0
{
    "aggs" : {
        "tag_cardinality" : {
            "cardinality" : {
                "field" : "tag",
                "missing": "N/A" <a id="CO185-1"></a><i class="conum" data-value="1"></i>
            }
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/338.console"></div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO185-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p>
<code class="literal">tag</code> 字段没有值的文档将与具有值 <code class="literal">N/A</code> 的文档落入相同的桶中。
</p>
</td>
</tr>
</table>
</div>
</div>

</div>
<div class="navfooter">
<span class="prev">
<a href="search-aggregations-metrics-boxplot-aggregation.html">« boxplot 聚合</a>
</span>
<span class="next">
<a href="search-aggregations-metrics-stats-aggregation.html">stats 聚合 »</a>
</span>
</div>
</div>

                  <!-- end body -->
                        </div>
                        <div class="col-xs-12 col-sm-4 col-md-4" id="right_col">
                        
                        </div>
                    </div>
                </div>
            </section>
        </div>
    </section>
</div>
<script src="../static/cn.js"></script>
</body>
</html>